
#pragma once

#include <cstdlib>

#include "os_basic_include_os.hpp"


#ifndef _MAKE__OBJECT__NOT__COPYABLE

    #define _MAKE__OBJECT__NOT__COPYABLE(Type) \
        Type(const Type&) = delete;            \
        Type(const Type&&) = delete;           \
        Type& operator=(const Type&) = delete; \
        Type& operator=(const Type&&) = delete;

#endif


namespace os_basic {

    //////////// STACK

    using StackDepthType = configSTACK_DEPTH_TYPE;

    constexpr StackDepthType MIN_STACK_DEPTH = configMINIMAL_STACK_SIZE;

    constexpr size_t MIN_STACK_DEPTH_IN_BYTES = configMINIMAL_STACK_SIZE * sizeof(StackType_t);


    //////////// PRIORITY

    // 至少应该有3 个优先级，去掉空闲优先级0，其他任务至少可以分成高、低两级
    static_assert(configMAX_PRIORITIES > 2);

    constexpr uint8_t HIGHEST_PRIORITY = configMAX_PRIORITIES - 1;

    // 需求不明确时，可以把大部分任务放在中间优先级，或者次高优先级，保留一个高优先级给高优先的任务
    constexpr uint8_t MIDDLE_PRIORITY = HIGHEST_PRIORITY - 1;

    constexpr uint8_t LOWEST_PRIORITY = 1;  // 最低任务优先级，但高于空闲任务优先级0

    constexpr uint8_t IDLE_PRIORITY = 0;

    /**
     * @brief 按相反顺序设置任务优先级，0 最高，1 次之，以此类推
     * 
     * 这样的好处是更容易表达最高优先级，以及次高优先级。
     * 
     * @param p 
     * @return constexpr uint8_t 
     */
    constexpr uint8_t reversed_priority(uint8_t p) {
        if(p > HIGHEST_PRIORITY) {
            return 0;
        }

        return HIGHEST_PRIORITY - p;
    }


    //////////// TICK

    constexpr uint16_t TICK_PERIOD = portTICK_PERIOD_MS;

    constexpr TickType_t ms(uint32_t val) {
        return val / TICK_PERIOD;
    }

    constexpr uint32_t tick_to_ms(TickType_t val) {
        return static_cast<uint32_t>(val * TICK_PERIOD);
    }

}  // namespace os_basic